package com.tim.arc.serialize.jacson;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.ser.std.StringSerializer;
import com.tim.arc.serialize.Person;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class Jackson {
    public static void main(String[] args) throws Exception {
        objectMapperDefault();
        objectMapperMixin();
    }

    public static void objectMapperDefault() throws JsonProcessingException {
        Person person=new Person("nana", 32, new Date());

        ObjectMapper objectMapper=new ObjectMapper();
        String str = objectMapper.writeValueAsString(person);
        System.out.println(str);
    }

    public static void objectMapperConfig() throws JsonProcessingException {
        /*
         spring:
            jackson:
              # 设置属性命名策略,对应jackson下PropertyNamingStrategy中的常量值，SNAKE_CASE-返回的json驼峰式转下划线，json body下划线传到后端自动转驼峰式
              property-naming-strategy: SNAKE_CASE
              # 全局设置@JsonFormat的格式pattern
              date-format: yyyy-MM-dd HH:mm:ss
              # 当地时区
              locale: zh
              # 设置全局时区
              time-zone: GMT+8
              # 常用，全局设置pojo或被@JsonInclude注解的属性的序列化方式
              default-property-inclusion: NON_NULL #不为空的属性才会序列化,具体属性可看JsonInclude.Include
              # 常规默认,枚举类SerializationFeature中的枚举属性为key，值为boolean设置jackson序列化特性,具体key请看SerializationFeature源码
              serialization:
                WRITE_DATES_AS_TIMESTAMPS: true # 返回的java.util.date转换成timestamp
                FAIL_ON_EMPTY_BEANS: true # 对象为空时是否报错，默认true
              # 枚举类DeserializationFeature中的枚举属性为key，值为boolean设置jackson反序列化特性,具体key请看DeserializationFeature源码
              deserialization:
                # 常用,json中含pojo不存在属性时是否失败报错,默认true
                FAIL_ON_UNKNOWN_PROPERTIES: false
              # 枚举类MapperFeature中的枚举属性为key，值为boolean设置jackson ObjectMapper特性
              # ObjectMapper在jackson中负责json的读写、json与pojo的互转、json tree的互转,具体特性请看MapperFeature,常规默认即可
              mapper:
                # 使用getter取代setter探测属性，如类中含getName()但不包含name属性与setName()，传输的vo json格式模板中依旧含name属性
                USE_GETTERS_AS_SETTERS: true #默认false
              # 枚举类JsonParser.Feature枚举类中的枚举属性为key，值为boolean设置jackson JsonParser特性
              # JsonParser在jackson中负责json内容的读取,具体特性请看JsonParser.Feature，一般无需设置默认即可
              parser:
                ALLOW_SINGLE_QUOTES: true # 是否允许出现单引号,默认false
              # 枚举类JsonGenerator.Feature枚举类中的枚举属性为key，值为boolean设置jackson JsonGenerator特性，一般无需设置默认即可
              # JsonGenerator在jackson中负责编写json内容,具体特性请看JsonGenerator.Feature
        * */

        //序列化、反序列化配置。ObjectMapper
        Object e1=MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS;
        // 序列化配置。ObjectMapper、ObjectWriter
        Object e2= SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS;
        // 反序列化配置。ObjectMapper、ObjectReader
        Object e3= DeserializationFeature.USE_BIG_INTEGER_FOR_INTS;

        Jackson2ObjectMapperBuilderCustomizer customizer=(jacksonObjectMapperBuilder)->{
            jacksonObjectMapperBuilder.featuresToEnable();
            jacksonObjectMapperBuilder.featuresToDisable();

            jacksonObjectMapperBuilder.dateFormat(new SimpleDateFormat("yyyy"));
            jacksonObjectMapperBuilder.serializers(null);
            jacksonObjectMapperBuilder.deserializers(null);

            SimpleModule simpleModule = new SimpleModule();
            simpleModule.addSerializer(null);
            jacksonObjectMapperBuilder.modules(simpleModule);

        };

        JsonSerialize a1;
        JsonSerializer s1;
        JsonDeserialize a2;
        JsonDeserializer s2;
        /*
         * Date。
         * enum。@JsonFormat(shape = JsonFormat.Shape.OBJECT)
         * collection。
         * Number。
         * */
        JsonFormat format;
        JsonIgnore ignore;
        JsonView view;// 分组

    }

    public static void objectMapperMixin() throws JsonProcessingException {
        Person person=new Person("nana", 32, new Date());

        ObjectMapper objectMapper=new ObjectMapper();
        objectMapper.addMixIn(Person.class, ObjectMixin.class);
        String str = objectMapper.writeValueAsString(person);
        System.out.println(str);
    }

    /*按属性定制序列化策略*/
    public static void objectMapperModifier() throws JsonProcessingException {
        BeanSerializerModifier modifier=new BeanSerializerModifier(){
            public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
                for (BeanPropertyWriter writer : beanProperties) {
                    if (writer.getName().equals("email")
                            ||writer.getAnnotation(JsonFormat.class)!=null) {
                        writer.assignSerializer(new StringSerializer());
                    }
                }
                return beanProperties;
            }

            @Override
            public List<BeanPropertyWriter> orderProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
                return super.orderProperties(config, beanDesc, beanProperties);
            }
        };
        SimpleModule module = new SimpleModule("CustomModule");
        module.setSerializerModifier(modifier);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(module);

    }



}
